import * as cc from 'cc';
const { ccclass, property } = cc._decorator;

export const ANIMATION_SPEED = 1 / 8;

@ccclass('AnimationClipCreate')
export class AnimationClipCreate {
    animationClip: cc.AnimationClip;

    constructor(
        private spriteFrameDir: string,
        private wrapMode: cc.AnimationClip.WrapMode = cc.AnimationClip
            .WrapMode.Normal,
        private speed: number = ANIMATION_SPEED,
        private events: Array<cc.AnimationClip.IEvent> = [],
    ) {}

    async init() {
        //创建动画添加轨道
        this.animationClip = new cc.AnimationClip();
        this.animationClip.name = this.spriteFrameDir;
        this.animationClip.wrapMode = this.wrapMode;

        const track = new cc.animation.ObjectTrack();

        // 属性路径
        track.path = new cc.animation.TrackPath()
            .toComponent(cc.Sprite)
            .toProperty('spriteFrame');

        // 加载图片
        const waiting = loadDir(this.spriteFrameDir, cc.SpriteFrame);
        waiting.then((spriteFrames) => {
            const frames: Array<[number, cc.SpriteFrame]> =
                sortSpriteFrame(spriteFrames).map((item, index) => [
                    index * this.speed,
                    item,
                ]);

            track.channel.curve.assignSorted(frames);

            // 动态设置动画时长
            this.animationClip.duration = frames.length * this.speed;
            this.animationClip.addTrack(track);

            for (const event of this.events) {
                this.animationClip.events.push(event);
            }
        });
        return waiting;
        // this.animationClip.updateEventDatas()
    }

    run(animation: cc.Animation) {
        if (animation.defaultClip.name === this.animationClip.name) {
            return;
        }
        animation.defaultClip = this.animationClip;
        animation.play();
    }

    start() {}

    update(deltaTime: number) {}
}

function loadDir(
    path: string,
    type: typeof cc.SpriteFrame = cc.SpriteFrame,
) {
    return new Promise<cc.SpriteFrame[]>((resolve, reject) => {
        cc.resources.loadDir<cc.SpriteFrame>(path, type, (err, res) => {
            if (err) {
                reject(err);
                return;
            }
            resolve(res);
        });
    });
}

const INDEX_REG = /\((\d+)\)/;

const getNumberWithinString = (str: string) =>
    parseInt(str.match(INDEX_REG)?.[1] || '0');

export const sortSpriteFrame = (spriteFrame: Array<cc.SpriteFrame>) =>
    spriteFrame.sort(
        (a, b) =>
            getNumberWithinString(a.name) - getNumberWithinString(b.name),
    );
